/****************************************************
	文件：HTTimer.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2021/1/10 12:48:6
	功能：计时器
*****************************************************/

using System;
using System.Collections.Generic;
using System.Timers;
using HTFW.Consts;

namespace HTFW.Core
{
    public class HTTimer
    {
        #region 字段

        #region 日志打印接口

        /// <summary>
        /// 打印日志接口
        /// </summary>
        private Action<string> mTaskLog;

        #endregion

        #region 服务器端使用

        /// <summary>
        /// 计时开始时间（计算机元年）
        /// </summary>
        private DateTime mStartDataTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);

        /// <summary>
        /// 当前时间
        /// </summary>
        private double mNowTime;

        /// <summary>
        /// 服务器端计时器
        /// </summary>
        private Timer mServerTimer;

        /// <summary>
        /// 服务器端使用
        /// 使用委托将定时任务包裹一层
        /// 控制，使其在服务器主线程执行
        /// Action（任务回调，任务全局id）
        /// </summary>
        private Action<Action<int>, int> mTaskHandle;

        #endregion

        #region 全局id

        /// <summary>
        /// 锁
        /// （生成全局id时使用）
        /// </summary>
        private static readonly string mLockTID = "lockTID";

        /// <summary>
        /// 全局id
        /// </summary>
        private int mTID;

        /// <summary>
        /// 缓存所有全局id
        /// </summary>
        private List<int> mTIDs = new List<int>();

        /// <summary>
        /// 缓存使用完了的、待回收的全局id
        /// </summary>
        private List<int> mTempRecycleTIDs = new List<int>();

        #endregion

        #region 计时任务 TimeTask

        /// <summary>
        /// 锁
        /// （TimeTask使用）
        /// </summary>
        private static readonly string mLockTime = "lockTime";

        /// <summary>
        /// 缓存计时任务
        /// </summary>
        private List<TimeTask> mTimeTasks = new List<TimeTask>();

        /// <summary>
        /// 计时任务的临时缓存
        /// </summary>
        private List<TimeTask> mTempTimeTasks = new List<TimeTask>();

        /// <summary>
        /// 待删除的计时任务的临时缓存
        /// （缓存的待删除任务的TID）
        /// </summary>
        private List<int> mTempDeleteTimeTasks = new List<int>();

        #endregion

        #region 帧任务 FrameTask

        /// <summary>
        /// 锁
        /// （FrameTask使用）
        /// </summary>
        private static readonly string mLockFrame = "lockFrame";

        /// <summary>
        /// 帧计数
        /// （获得当前帧）
        /// </summary>
        private int mFrameCounter;

        /// <summary>
        /// 缓存所有帧任务
        /// </summary>
        private List<FrameTask> mFrameTasks = new List<FrameTask>();

        /// <summary>
        /// 帧任务的临时缓存
        /// </summary>
        private List<FrameTask> mTempFrameTasks = new List<FrameTask>();

        /// <summary>
        /// 待删除的帧任务的临时缓存
        /// </summary>
        private List<int> mTempDeleteFrameTasks = new List<int>();

        #endregion

        #endregion


        #region 初始化

        /// <summary>
        /// 构造函数
        /// interval：服务器中的计时器的Update执行的时间间隔（默认为0毫秒）
        /// </summary>
        public HTTimer(int interval = 0)
        {
            //初始化（清空缓存）
            mTIDs.Clear();
            mTempRecycleTIDs.Clear();
            mTimeTasks.Clear();
            mTempTimeTasks.Clear();
            mFrameTasks.Clear();
            mTempFrameTasks.Clear();

            if (interval != 0)
            {
                //服务器的计时器
                mServerTimer = new Timer(interval)
                {
                    //循环
                    AutoReset = true,
                };
                mServerTimer.Elapsed += (object sender, ElapsedEventArgs args) =>
                {
                    //每次循环都会执行一次Update
                    Update();
                };
                mServerTimer.Start();
            }
        }

        #endregion


        #region Update

        public void Update()
        {
            CheckTimeTask();
            CheckFrameTask();

            RemoveTimeTask();
            RemoveFrameTask();

            //回收TID
            if (mTempRecycleTIDs.Count > 0)
            {
                lock (mLockTID) //锁
                {
                    //回收TID
                    RecycleTID();
                }
            }
        }

        /// <summary>
        /// 检测计时任务
        /// </summary>
        private void CheckTimeTask()
        {
            //当计时任务临时缓存不为空时
            if (mTempTimeTasks.Count > 0)
            {
                lock (mLockTime)
                {
                    //将临时缓存中的计时任务加载到计时任务缓存中
                    for (int i = 0; i < mTempTimeTasks.Count; i++)
                    {
                        mTimeTasks.Add(mTempTimeTasks[i]);
                    }

                    //清空临时缓存
                    mTempTimeTasks.Clear();
                }
            }

            //更新当前时间（毫秒）
            mNowTime = GetUTCMilliseconds();

            //遍历任务是否达到执行时间（ActTime达到）
            for (int i = 0; i < mTimeTasks.Count; i++)
            {
                //获取计时任务
                TimeTask task = mTimeTasks[i];

                //还没到目标执行时间
                if (mNowTime.CompareTo(task.ActTime) < 0)
                {
                    continue;
                }
                //到了目标执行时间
                else
                {
                    //1.获取任务回调
                    Action<int> action = task.CallBack;
                    //2.执行任务回调
                    try
                    {
                        //a.服务器中使用的（在主线程执行所有计时任务的回调）
                        if (mTaskHandle != null)
                        {
                            mTaskHandle(action, task.TID);
                        }
                        //b.Unity中使用的
                        else
                        {
                            if (action != null)
                            {
                                action(task.TID);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        //输出异常信息
                        LogInfo(e.ToString());
                    }

                    //3.移除完成的任务
                    //执行一次的任务（当下执行完成了，可以移除）
                    if (task.LoopCount == 1)
                    {
                        //移除任务
                        mTimeTasks.RemoveAt(i);
                        //索引回退
                        i--;
                        //添加移除的任务的全局id到 缓存（回收TID）
                        mTempRecycleTIDs.Add(task.TID);
                    }
                    //执行多次的任务（更新任务数据）
                    else
                    {
                        if (task.LoopCount > 1)
                        {
                            //更新循环次数
                            task.LoopCount -= 1;
                        }

                        //更新任务执行时间
                        task.ActTime += task.DelayTime;
                    }
                }
            }
        }

        /// <summary>
        /// 删除计时任务
        /// </summary>
        private void RemoveTimeTask()
        {
            //当待删除的计时任务的临时缓存不为空时
            if (mTempDeleteTimeTasks.Count > 0)
            {
                lock (mLockTime)
                {
                    for (int i = 0; i < mTempDeleteTimeTasks.Count; i++)
                    {
                        //是否删除的标志位
                        bool isDelete = false;
                        //待删除任务的TID
                        int deleteTID = mTempDeleteTimeTasks[i];
                        //1.遍历  计时任务缓存，寻找待删除任务、并删除
                        for (int j = 0; j < mTimeTasks.Count; j++)
                        {
                            TimeTask task = mTimeTasks[j];
                            if (task.TID == deleteTID)
                            {
                                //移除任务（此处移除之后就跳出当层循环，所以不需要索引回退）
                                mTimeTasks.RemoveAt(j);
                                //添加移除的任务的全局id到 缓存（回收TID）
                                mTempRecycleTIDs.Add(deleteTID);
                                //更新标志位
                                isDelete = true;
                                LogInfo("删除计时任务，线程id：" +
                                        System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());
                                break;
                            }
                        }

                        if (isDelete)
                        {
                            continue;
                        }

                        //2.遍历  计时任务临时缓存，寻找待删除任务、并删除
                        for (int k = 0; k < mTempTimeTasks.Count; k++)
                        {
                            TimeTask task = mTempTimeTasks[k];
                            if (task.TID == deleteTID)
                            {
                                //移除任务
                                mTempTimeTasks.RemoveAt(k);
                                //添加移除的任务的全局id到 缓存（回收TID）
                                mTempRecycleTIDs.Add(deleteTID);
                                LogInfo("删除计时任务，线程id：" +
                                        System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());
                                break;
                            }
                        }
                    }

                    //删除所有待删除任务后  清空缓存
                    mTempDeleteTimeTasks.Clear();
                }
            }
        }

        /// <summary>
        /// 检测帧任务
        /// </summary>
        private void CheckFrameTask()
        {
            //当帧任务临时缓存不为空时
            if (mTempFrameTasks.Count > 0)
            {
                lock (mLockFrame)
                {
                    //将临时缓存中的帧任务加载到帧任务缓存中
                    for (int i = 0; i < mTempFrameTasks.Count; i++)
                    {
                        mFrameTasks.Add(mTempFrameTasks[i]);
                    }

                    //清空临时缓存
                    mTempFrameTasks.Clear();
                }
            }

            //更新当前帧
            mFrameCounter += 1;

            //遍历任务是否达到执行帧（ActFrame达到）
            for (int i = 0; i < mFrameTasks.Count; i++)
            {
                //获取帧任务
                FrameTask task = mFrameTasks[i];

                //还没到目标执行帧
                if (mFrameCounter < task.ActFrame)
                {
                    continue;
                }
                //到了目标执行帧
                else
                {
                    //1.获取任务回调
                    Action<int> action = task.CallBack;
                    //2.执行任务回调
                    try
                    {
                        //a.服务器中使用的（在主线程执行所有计时任务的回调）
                        if (mTaskHandle != null)
                        {
                            mTaskHandle(action, task.TID);
                        }
                        //b.Unity中使用的
                        else
                        {
                            if (action != null)
                            {
                                action(task.TID);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        //输出异常信息
                        LogInfo(e.ToString());
                    }

                    //3.移除完成的任务
                    //执行一次的任务（当下执行完成了，可以移除）
                    if (task.LoopCount == 1)
                    {
                        //移除任务
                        mFrameTasks.RemoveAt(i);
                        //索引回退
                        i--;
                        //添加移除的任务的全局id到 缓存（回收TID）
                        mTempRecycleTIDs.Add(task.TID);
                    }
                    //执行多次的任务（更新任务数据）
                    else
                    {
                        if (task.LoopCount > 1)
                        {
                            //更新循环次数
                            task.LoopCount -= 1;
                        }

                        //更新任务执行时间
                        task.ActFrame += task.DelayFrame;
                    }
                }
            }
        }

        /// <summary>
        /// 删除帧任务
        /// </summary>
        private void RemoveFrameTask()
        {
            //当待删除的帧任务的临时缓存不为空时
            if (mTempDeleteFrameTasks.Count > 0)
            {
                lock (mLockFrame)
                {
                    for (int i = 0; i < mTempDeleteFrameTasks.Count; i++)
                    {
                        //是否删除的标志位
                        bool isDelete = false;
                        //待删除任务的TID
                        int deleteTID = mTempDeleteFrameTasks[i];
                        //1.遍历  帧任务缓存，寻找待删除任务、并删除
                        for (int j = 0; j < mFrameTasks.Count; j++)
                        {
                            FrameTask task = mFrameTasks[j];
                            if (task.TID == deleteTID)
                            {
                                //移除任务（此处移除之后就跳出当层循环，所以不需要索引回退）
                                mFrameTasks.RemoveAt(j);
                                //添加移除的任务的全局id到 缓存（回收TID）
                                mTempRecycleTIDs.Add(deleteTID);
                                //更新标志位
                                isDelete = true;
                                LogInfo(
                                    "删除帧任务，线程id：" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());
                                break;
                            }
                        }

                        if (isDelete)
                        {
                            continue;
                        }

                        //2.遍历  帧任务临时缓存，寻找待删除任务、并删除
                        for (int k = 0; k < mTempFrameTasks.Count; k++)
                        {
                            FrameTask task = mTempFrameTasks[k];
                            if (task.TID == deleteTID)
                            {
                                //移除任务
                                mTempFrameTasks.RemoveAt(k);
                                //添加移除的任务的全局id到 缓存（回收TID）
                                mTempRecycleTIDs.Add(deleteTID);
                                LogInfo(
                                    "删除帧任务，线程id：" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());
                                break;
                            }
                        }
                    }

                    //删除所有待删除任务后  清空缓存
                    mTempDeleteFrameTasks.Clear();
                }
            }
        }

        /// <summary>
        /// 回收全局ID
        /// </summary>
        private void RecycleTID()
        {
            //遍历  待回收的  缓存列表
            for (int i = 0; i < mTempRecycleTIDs.Count; i++)
            {
                int recycleTID = mTempRecycleTIDs[i];
                //遍历  所有TID的  缓存列表
                for (int j = 0; j < mTIDs.Count; j++)
                {
                    if (mTIDs[j] == recycleTID)
                    {
                        //移除
                        mTIDs.RemoveAt(j);
                        break;
                    }
                }
            }

            //清空缓存
            mTempRecycleTIDs.Clear();
        }

        #endregion


        #region TimeTask （对外开放的  计时任务  的API）

        /// <summary>
        /// 添加计时任务
        /// 返回此任务的全局ID
        /// </summary>
        /// <param name="callBack">计时任务回调</param>
        /// <param name="delayTime">延迟时间</param>
        /// <param name="timeUnit">时间单位</param>
        /// <param name="loopCount">循环次数</param>
        /// <returns></returns>
        public int AddTimeTask(Action<int> callBack, double delayTime, TimeUnit timeUnit = TimeUnit.MilliSecond,
            int loopCount = 1)
        {
            //时间单位换算
            if (timeUnit != TimeUnit.MilliSecond)
            {
                switch (timeUnit)
                {
                    case TimeUnit.Second:
                        delayTime = delayTime * 1000;
                        break;
                    case TimeUnit.Minute:
                        delayTime = delayTime * 1000 * 60;
                        break;
                    case TimeUnit.Hour:
                        delayTime = delayTime * 1000 * 60 * 60;
                        break;
                    case TimeUnit.Day:
                        delayTime = delayTime * 1000 * 60 * 60 * 24;
                        break;
                    default:
                        LogInfo("AddTimeTask出错！时间换算中出现了未定义的时间单位：" + timeUnit);
                        break;
                }
            }

            //生成一个TID
            int tID = GetTID();
            //任务执行时间
            double actTime = GetUTCMilliseconds() + delayTime;
            //添加到临时缓存
            lock (mLockTime)
            {
                mTempTimeTasks.Add(new TimeTask(tID, callBack, delayTime, actTime, loopCount));
            }

            LogInfo("添加计时任务");
            return tID;
        }

        /// <summary>
        /// 移除计时任务
        /// </summary>
        /// <param 任务的全局ID="tID"></param>
        public void RemoveTimeTask(int tID)
        {
            lock (mLockTime)
            {
                //添加到临时缓存
                mTempDeleteTimeTasks.Add(tID);
            }
        }

        /// <summary>
        /// 移除所有的计时任务
        /// </summary>
        public void RemoveAllTimeTask()
        {
            lock (mLockTime)
            {
                foreach (var timeTask in mTempTimeTasks)
                    mTempDeleteTimeTasks.Add(timeTask.TID);

                foreach (var timeTask in mTimeTasks)
                    mTempDeleteTimeTasks.Add(timeTask.TID);
            }

            LogInfo("RemoveAllTimeTask done.");
        }

        /// <summary>
        /// 替换计时任务
        /// 返回bool（是否替换成功）
        /// </summary>
        /// <param name="tID">待替换任务的全局ID</param>
        /// <param name="callBack">计时任务回调</param>
        /// <param name="delayTime">延迟时间</param>
        /// <param name="timeUnit">时间单位</param>
        /// <param name="loopCount">循环次数</param>
        /// <returns></returns>
        public bool ReplaceTimeTask(int tID, Action<int> callBack, double delayTime,
            TimeUnit timeUnit = TimeUnit.MilliSecond, int loopCount = 1)
        {
            //时间单位换算
            if (timeUnit != TimeUnit.MilliSecond)
            {
                switch (timeUnit)
                {
                    case TimeUnit.Second:
                        delayTime = delayTime * 1000;
                        break;
                    case TimeUnit.Minute:
                        delayTime = delayTime * 1000 * 60;
                        break;
                    case TimeUnit.Hour:
                        delayTime = delayTime * 1000 * 60 * 60;
                        break;
                    case TimeUnit.Day:
                        delayTime = delayTime * 1000 * 60 * 60 * 24;
                        break;
                    default:
                        LogInfo("AddTimeTask出错！时间换算中出现了未定义的时间单位：" + timeUnit);
                        break;
                }
            }

            //任务执行时间
            double actTime = GetUTCMilliseconds() + delayTime;
            //创建计时任务
            TimeTask newTask = new TimeTask(tID, callBack, delayTime, actTime, loopCount);
            //替换计时任务：
            //替换成功与否的标志位
            bool isReplaced = false;
            //1.遍历  计时任务缓存
            for (int i = 0; i < mTimeTasks.Count; i++)
            {
                if (mTimeTasks[i].TID == tID)
                {
                    //替换任务
                    mTimeTasks[i] = newTask;
                    //更新标志位
                    isReplaced = true;
                    break;
                }
            }

            if (isReplaced == false)
            {
                //2.遍历  计时任务临时缓存
                for (int i = 0; i < mTempTimeTasks.Count; i++)
                {
                    if (mTempTimeTasks[i].TID == tID)
                    {
                        //替换任务
                        mTempTimeTasks[i] = newTask;
                        //更新标志位
                        isReplaced = true;
                        break;
                    }
                }
            }

            return isReplaced;
        }

        #endregion


        #region FrameTask （对外开放的  帧任务  的API）

        /// <summary>
        /// 添加帧任务
        /// 返回此任务的全局ID
        /// </summary>
        /// <param name="callBack">帧任务回调</param>
        /// <param name="delayFrame">延迟帧</param>
        /// <param name="loopCount">循环次数</param>
        /// <returns></returns>
        public int AddFrameTask(Action<int> callBack, int delayFrame, int loopCount = 1)
        {
            //生成一个TID
            int tID = GetTID();
            //任务执行帧
            int actFrame = mFrameCounter + delayFrame;
            //添加到临时缓存
            lock (mLockFrame)
            {
                mTempFrameTasks.Add(new FrameTask(tID, callBack, delayFrame, actFrame, loopCount));
            }

            LogInfo("添加帧任务");
            return tID;
        }

        /// <summary>
        /// 移除帧任务
        /// </summary>
        /// <param name="tID">任务的全局ID</param>
        public void RemoveFrameTask(int tID)
        {
            lock (mLockFrame)
            {
                //添加到临时缓存
                mTempDeleteFrameTasks.Add(tID);
            }
        }

        /// <summary>
        /// 移除所有帧任务
        /// </summary>
        public void RemoveAllFrameTask()
        {
            lock (mLockFrame)
            {
                foreach (var frameTask in mTempFrameTasks)
                    mTempDeleteFrameTasks.Add(frameTask.TID);

                foreach (var frameTask in mFrameTasks)
                    mTempDeleteFrameTasks.Add(frameTask.TID);
            }

            LogInfo("RemoveAllFrameTask done.");
        }

        /// <summary>
        /// 替换帧任务
        /// 返回bool（是否替换成功）
        /// </summary>
        /// <param name="tID">待替换任务的全局ID</param>
        /// <param name="callBack">帧任务回调</param>
        /// <param name="delayFrame">延迟帧</param>
        /// <param name="loopCount">循环次数</param>
        /// <returns></returns>
        public bool ReplaceFrameTask(int tID, Action<int> callBack, int delayFrame, int loopCount = 1)
        {
            //任务执行帧
            int actFrame = mFrameCounter + delayFrame;
            //创建帧任务
            FrameTask newTask = new FrameTask(tID, callBack, delayFrame, actFrame, loopCount);
            //替换帧任务：
            //替换成功与否的标志位
            bool isReplaced = false;
            //1.遍历  帧任务缓存
            for (int i = 0; i < mFrameTasks.Count; i++)
            {
                if (mFrameTasks[i].TID == tID)
                {
                    //替换任务
                    mFrameTasks[i] = newTask;
                    //更新标志位
                    isReplaced = true;
                    break;
                }
            }

            if (isReplaced == false)
            {
                //2.遍历  帧任务临时缓存
                for (int i = 0; i < mTempFrameTasks.Count; i++)
                {
                    if (mTempFrameTasks[i].TID == tID)
                    {
                        //替换任务
                        mTempFrameTasks[i] = newTask;
                        //更新标志位
                        isReplaced = true;
                        break;
                    }
                }
            }

            return isReplaced;
        }

        #endregion


        #region Others （对外开放的 API）

        /// <summary>
        /// 设置打印日志接口
        /// </summary>
        public void SetLog(Action<string> log)
        {
            mTaskLog = log;
        }

        /// <summary>
        /// 设置TaskHandle
        /// （服务器使用：在主线程执行所有计时任务的回调）
        /// </summary>
        public void SetTaskHandle(Action<Action<int>, int> taskHandle)
        {
            mTaskHandle = taskHandle;
        }

        /// <summary>
        /// 清空计时器
        /// </summary>
        public void Dispose()
        {
            //重置全局ID计数
            mTID = 0;
            //清空缓存
            mTIDs.Clear();
            mTempRecycleTIDs.Clear();

            mTimeTasks.Clear();
            mTempTimeTasks.Clear();

            mFrameTasks.Clear();
            mTempFrameTasks.Clear();

            mTempDeleteTimeTasks.Clear();
            mTempDeleteFrameTasks.Clear();

            //打印日志接口 置空
            mTaskLog = null;
            //关闭计时器（服务器使用）
            mServerTimer?.Stop();
        }

        /// <summary>
        /// 获取当前时间（毫秒）
        /// </summary>
        public double GetMillisecondsTime()
        {
            return mNowTime;
        }

        /// <summary>
        /// 获取当前时区的时间（本地时间）
        /// </summary>
        public DateTime GetLocalDateTime()
        {
            /*
             * TimeZone已过时
             * 使用TimeZoneInfo
             * TimeZoneInfo.ConvertTimeFromUtc：将UTC（世界标准时间）转化为指定时区时间
             * TimeZoneInfo.Local为计算机本地时区
             */

            //DateTime dateTime = TimeZone.CurrentTimeZone.ToLocalTime(mStartDataTime.AddMilliseconds(mNowTime));

            DateTime dateTime =
                TimeZoneInfo.ConvertTimeFromUtc(mStartDataTime.AddMilliseconds(mNowTime), TimeZoneInfo.Local);
            return dateTime;
        }

        /// <summary>
        /// 获取本地时间的字符串
        /// 格式：15:45:05
        /// </summary>
        /// <returns></returns>
        public string GetLocalTimeStr()
        {
            DateTime dateTime = GetLocalDateTime();
            string str = Time2Str(dateTime.Hour) + ":" + Time2Str(dateTime.Minute) + ":" + Time2Str(dateTime.Second);
            return str;
        }

        /// <summary>
        /// 获取年（本地时间）
        /// </summary>
        public int GetYear()
        {
            return GetLocalDateTime().Year;
        }

        /// <summary>
        /// 获取月（本地时间）
        /// </summary>
        public int GetMonth()
        {
            return GetLocalDateTime().Month;
        }

        /// <summary>
        /// 获取星期（本地时间）
        /// </summary>
        public int GetWeek()
        {
            return (int) GetLocalDateTime().DayOfWeek;
        }

        /// <summary>
        /// 获取日（本地时间）
        /// </summary>
        public int GetDay()
        {
            return GetLocalDateTime().Day;
        }

        #endregion


        #region ToolMethods

        /// <summary>
        /// 生成全局ID
        /// </summary>
        private int GetTID()
        {
            lock (mLockTID)
            {
                //全局ID自增
                mTID += 1;
                //容错处理：
                //防止int超出上界、防止mTID重复使用
                while (true)
                {
                    //达到int上界
                    if (mTID == int.MaxValue)
                    {
                        //重置
                        mTID = 0;
                    }

                    //是否使用过的标志位
                    bool isUsed = false;
                    //遍历缓存，检查mTID是否使用过
                    for (int i = 0; i < mTIDs.Count; i++)
                    {
                        if (mTIDs[i] == mTID)
                        {
                            //使用过
                            isUsed = true;
                            break;
                        }
                    }

                    //mTID使用过
                    if (isUsed)
                    {
                        //自增
                        mTID += 1;
                    }
                    //mTID没有使用过
                    else
                    {
                        //添加到缓存
                        mTIDs.Add(mTID);
                        break;
                    }
                }
            }

            return mTID;
        }

        #endregion


        #region TimeHelper

        /// <summary>
        /// 获取当前时间数（单位：毫秒）
        /// 当前的标准时间（UTC）到计算机元年（1970，1，1，0，0，0，0）的时间间隔
        /// </summary>
        private double GetUTCMilliseconds()
        {
            //当前的标准时间（UTC）到计算机元年（1970，1，1，0，0，0，0）的时间间隔
            TimeSpan ts = DateTime.UtcNow - mStartDataTime;
            return ts.TotalMilliseconds;
        }

        /// <summary>
        /// 将时间转变为字符串
        /// eg：5=>05
        /// </summary>
        private string Time2Str(int time)
        {
            if (time < 10)
            {
                return "0" + time;
            }
            else
            {
                return time.ToString();
            }
        }

        #endregion


        #region Log

        /// <summary>
        /// 打印消息
        /// </summary>
        private void LogInfo(string info)
        {
            mTaskLog?.Invoke(info);
        }

        #endregion
    }
}